﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using CncConvProg.Geometry;
using CncConvProg.Geometry.Entity;
using CncConvProg.Geometry.RawProfile2D;
using CncConvProg.Model.ConversationalStructure.Abstraction;
using CncConvProg.Model.ConversationalStructure.Lavorazioni.Common;
using CncConvProg.Model.ConversationalStructure.Lavorazioni.Fresatura.Pattern;
using CncConvProg.Model.PathGenerator;
using CncConvProg.Model.Tool;
using CncConvProg.Model.Tool.Mill;
using CncConvProg.Model.Tool.Parametro;

/*
 * 
 * meglio aggiungere pattern se poi ne ho occasione dare opt. abilitato o meno..
 * 
 */

namespace CncConvProg.Model.ConversationalStructure.Lavorazioni.Fresatura
{
    [Serializable]
    public sealed class FresaturaCava : LavorazioneFresatura, IMillingPatternable, IMillWorkable
    {
        public FresaturaCava()
            : base()
        {
            MillingPattern = EnumPatternMilling.Rettangolo;

            Sgrossatura = new Operazione(this, LavorazioniEnumOperazioni.Sgrossatura);
            Finitura = new Operazione(this, LavorazioniEnumOperazioni.Finitura);
            //CentrinoForoApertura = new Operazione(this, (int)FresaturaEnumOperazioni.Centrino);
            //ForaturaApertura = new Operazione(this, (int)FresaturaEnumOperazioni.Foratura);
            Smussatura = new Operazione(this, LavorazioniEnumOperazioni.Smussatura);


        }

        public IMillingPattern Pattern { get; private set; }

        private EnumPatternMilling _millingPattern;
        public EnumPatternMilling MillingPattern
        {
            get
            {
                return _millingPattern;
            }
            set
            {
                _millingPattern = value;
                UpdatePattern();
            }
        }
        private void UpdatePattern()
        {
            Pattern = MillPatternHelper.GetPattern(MillingPattern);
        }

        public RawProfile Profile { get; set; }

        public double ProfonditaLavorazione { get; set; }

        public double InizioLavorazioneZ { get; set; }

        public override List<Operazione> Operazioni
        {
            get
            {
                var opList = new List<Operazione>();

                //if (Sgrossatura.Abilitata)
                opList.Add(Sgrossatura);

                //if (Finitura.Abilitata)
                opList.Add(Finitura);

                //if (Smussatura.Abilitata)
                opList.Add(Smussatura);

                return opList;
            }
        }

        public Operazione Sgrossatura { get; set; }

        public Operazione Finitura { get; set; }

        public Operazione Smussatura { get; set; }

        //public Operazione CentrinoForoApertura { get; set; }

        //public Operazione ForaturaApertura { get; set; }

        public double ProfonditaFresaSmussatura { get; set; }

        public bool FinishWithCompensation { get; set; }

        public double SovrametalloFinituraProfilo { get; set; }

        public double SovrametalloFinituraZ { get; set; }

        public bool ChamferWithCompensation { get; set; }

        //internal override Utensile CreateTool(LavorazioniEnumOperazioni enumOperationType)
        //{
        //    var unit = Singleton.Instance.MeasureUnit;

        //    return FresaturaHelper.CreateTool((LavorazioniEnumOperazioni)enumOperationType, unit);
        //}

        //internal override List<Utensile> GetCompatibleTools(LavorazioniEnumOperazioni operationType, MagazzinoUtensile magazzino)
        //{
        //    // todo su nessun utensile probabilmente crasha..
        //    var unit = Singleton.Instance.MeasureUnit;

        //    return magazzino.GetTools<FresaCandela>(unit).Cast<Utensile>().ToList();
        //}


        public override void SetProfile(List<RawEntity2D> list)
        {
            Profile.Syncronize(list);

            base.SetProfile(list);
        }

        private Profile2D GetProfile()
        {
            if (Pattern != null)
                return Pattern.GetClosedProfile();

            return null;
        }


        protected override void CreateSpecificProgram(ProgramPhase programPhase, Operazione operazione)
        {
            var diametrable = operazione.Utensile as IDiametrable;

            var parametro = operazione.Utensile.ParametroUtensile as ParametroFresaCandela;

            if (diametrable == null) return;

            var diaFresa = diametrable.Diametro;


            double profPassata = 0;
            double larghezzaPassata = 0;

            if (parametro != null)
            {
                profPassata = parametro.GetProfonditaPassata();

                larghezzaPassata = parametro.GetLarghezzaPassata();
            }

            var secZ = InizioLavorazioneZ + ExtraCorsa;
            var moveCollection = new MoveActionCollection();

            var workProfile = GetProfile();

            switch (operazione.OperationType)
            {
                case LavorazioniEnumOperazioni.Sgrossatura:
                    {
                        var sovraXy = SovrametalloFinituraProfilo;

                        if (!Finitura.Abilitata)
                            sovraXy = 0;

                        MillProgrammingHelper.GetInternRoughing(moveCollection, workProfile, ProfonditaLavorazione,
                                                                profPassata, larghezzaPassata, diaFresa, ExtraCorsa,
                                                                 InizioLavorazioneZ, secZ,
                                                                sovraXy, SovrametalloFinituraZ);

                    } break;

                case LavorazioniEnumOperazioni.Finitura:
                    {
                        MillProgrammingHelper.GetInternFinish(moveCollection, workProfile, ProfonditaLavorazione, profPassata, diaFresa, ExtraCorsa, FinishWithCompensation, InizioLavorazioneZ, secZ);
                    } break;

                case LavorazioniEnumOperazioni.Smussatura:
                    {
                        ProfonditaFresaSmussatura = diaFresa / 2;

                        MillProgrammingHelper.GetInternChamfer(moveCollection, workProfile, ProfonditaFresaSmussatura,
                                                               diaFresa, ExtraCorsa, ChamferWithCompensation,
                                                               InizioLavorazioneZ, secZ);
                    } break;

                default:
                    {
                        Debug.Fail("FresaturaCava.GetOperationProgram");
                    } break;

            }
            var mm = base.GetFinalProgram(moveCollection);

            foreach (var variable in mm)
            {
                programPhase.AddMoveAction(variable);
            }

        }

        public override string Descrizione
        {
            get { return MecPrev.Resources.GuiRes.PocketOp; }
        }

        /// <summary>
        /// Ritorna anteprima della lavorazione
        /// </summary>
        /// <returns></returns>
        protected override List<IEntity3D> GetFinalPreview()
        {
            try
            {
                if (Pattern != null)
                {
                    var preview = Pattern.GetClosedProfile().Source;

                    return Entity3DHelper.Get3DProfile(preview).ToList();
                }

            }
            catch (Exception ex)
            {
            }

            return null;
        }

    }


}






